package com.team.order.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 模拟支付SDK
 * 用于模拟第三方支付功能，便于测试业务流程
 * @author 梁国瑞
 */
@Slf4j
@Component
public class MockPaymentSDK {
    
    @Autowired
    private com.team.order.mapper.AppOrderMapper appOrderMapper;
    
    @Autowired
    private com.team.order.service.AccountFlowService accountFlowService;
    
    // 模拟支付订单存储
    private static final ConcurrentHashMap<String, MockPaymentOrder> PAYMENT_ORDERS = new ConcurrentHashMap<>();
    
    // 模拟配置
    private static final String MOCK_APP_ID = "mock_app_id_123456";
    private static final String MOCK_MERCHANT_ID = "mock_merchant_123456";
    private static final String MOCK_SECRET_KEY = "mock_secret_key_abcdef";
    
    /**
     * 创建微信支付订单
     */
    public Map<String, String> createWechatPayOrder(String orderNo, BigDecimal amount, String description) {
        log.info("模拟创建微信支付订单，订单号：{}，金额：{}", orderNo, amount);
        
        // 生成模拟的支付参数
        Map<String, String> params = new HashMap<>();
        params.put("appid", MOCK_APP_ID);
        params.put("mch_id", MOCK_MERCHANT_ID);
        params.put("nonce_str", generateNonceStr());
        params.put("body", description);
        params.put("out_trade_no", orderNo);
        params.put("total_fee", amount.multiply(new BigDecimal("100")).intValue() + "");
        params.put("spbill_create_ip", "127.0.0.1");
        params.put("notify_url", "http://localhost:8080/payment/callback");
        params.put("trade_type", "NATIVE");
        
        // 生成二维码URL（模拟）
        String qrCodeUrl = "";
        params.put("code_url", qrCodeUrl);
        
        // 生成签名
        String sign = generateMockSign(params);
        params.put("sign", sign);
        
        // 存储支付订单信息
        MockPaymentOrder paymentOrder = new MockPaymentOrder();
        paymentOrder.setOrderNo(orderNo);
        paymentOrder.setAmount(amount);
        paymentOrder.setPayType(0); // 微信支付
        paymentOrder.setStatus("PENDING");
        paymentOrder.setCreateTime(LocalDateTime.now());
        paymentOrder.setDescription(description);
        
        PAYMENT_ORDERS.put(orderNo, paymentOrder);
        
        log.info("模拟微信支付订单创建成功，订单号：{}", orderNo);
        return params;
    }
    
    /**
     * 创建支付宝支付订单
     */
    public Map<String, String> createAlipayOrder(String orderNo, BigDecimal amount, String subject) {
        log.info("模拟创建支付宝支付订单，订单号：{}，金额：{}", orderNo, amount);
        
        // 生成模拟的支付参数
        Map<String, String> params = new HashMap<>();
        params.put("app_id", MOCK_APP_ID);
        params.put("method", "alipay.trade.page.pay");
        params.put("charset", "utf-8");
        params.put("sign_type", "RSA2");
        params.put("timestamp", LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        params.put("version", "1.0");
        params.put("notify_url", "http://localhost:8080/payment/callback");
        
        // 构建业务参数
        String bizContent = String.format(
            "{\"out_trade_no\":\"%s\",\"total_amount\":\"%s\",\"subject\":\"%s\",\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}",
            orderNo, amount.toString(), subject
        );
        params.put("biz_content", bizContent);
        
        // 生成支付链接（模拟）
        String payUrl = "http://localhost:8080/mock/alipay/pay?orderNo=" + orderNo;
        params.put("pay_url", payUrl);
        
        // 生成签名
        String sign = generateMockSign(params);
        params.put("sign", sign);
        
        // 存储支付订单信息
        MockPaymentOrder paymentOrder = new MockPaymentOrder();
        paymentOrder.setOrderNo(orderNo);
        paymentOrder.setAmount(amount);
        paymentOrder.setPayType(1); // 支付宝
        paymentOrder.setStatus("PENDING");
        paymentOrder.setCreateTime(LocalDateTime.now());
        paymentOrder.setDescription(subject);
        
        PAYMENT_ORDERS.put(orderNo, paymentOrder);
        
        log.info("模拟支付宝支付订单创建成功，订单号：{}", orderNo);
        return params;
    }
    
    /**
     * 模拟支付成功
     */
    public boolean simulatePaymentSuccess(String orderNo) {
        MockPaymentOrder paymentOrder = PAYMENT_ORDERS.get(orderNo);
        if (paymentOrder == null) {
            log.error("支付订单不存在，订单号：{}", orderNo);
            return false;
        }
        
        if ("SUCCESS".equals(paymentOrder.getStatus())) {
            log.info("订单已支付成功，订单号：{}", orderNo);
            return true;
        }
        
        // 模拟支付成功
        paymentOrder.setStatus("SUCCESS");
        paymentOrder.setPayTime(LocalDateTime.now());
        paymentOrder.setThirdPartyOrderNo("TP" + System.currentTimeMillis());
        
        // 更新订单支付状态
        try {
            com.team.order.domain.Order order = appOrderMapper.selectOrderByOrderNo(orderNo);
            if (order != null) {
                // 更新订单支付状态
                appOrderMapper.updateOrderPaymentSuccess(
                    order.getId(), 
                    1L, // 已支付
                    LocalDateTime.now(), 
                    paymentOrder.getPayType().longValue(), 
                    paymentOrder.getThirdPartyOrderNo()
                );
                
                // 创建商户收支明细
                accountFlowService.createOrderIncomeFlow(
                    order.getId(),
                    orderNo,
                    order.getMerchantId(),
                    order.getPrice(),
                    paymentOrder.getPayType().longValue(),
                    paymentOrder.getThirdPartyOrderNo()
                );
                
                log.info("订单支付成功，已更新订单状态并创建收支明细，订单号：{}", orderNo);
            } else {
                log.warn("订单不存在，无法更新订单状态，订单号：{}", orderNo);
            }
        } catch (Exception e) {
            log.error("更新订单状态或创建收支明细失败，订单号：{}", orderNo, e);
        }
        
        log.info("模拟支付成功，订单号：{}", orderNo);
        return true;
    }
    
    /**
     * 模拟支付失败
     */
    public boolean simulatePaymentFail(String orderNo) {
        MockPaymentOrder paymentOrder = PAYMENT_ORDERS.get(orderNo);
        if (paymentOrder == null) {
            log.error("支付订单不存在，订单号：{}", orderNo);
            return false;
        }
        
        paymentOrder.setStatus("FAIL");
        paymentOrder.setFailReason("用户取消支付");
        
        log.info("模拟支付失败，订单号：{}", orderNo);
        return true;
    }
    
    /**
     * 查询支付状态
     */
    public String queryPaymentStatus(String orderNo) {
        MockPaymentOrder paymentOrder = PAYMENT_ORDERS.get(orderNo);
        if (paymentOrder == null) {
            return "NOT_FOUND";
        }
        return paymentOrder.getStatus();
    }
    
    /**
     * 模拟退款
     */
    public boolean refund(String orderNo, BigDecimal amount) {
        MockPaymentOrder paymentOrder = PAYMENT_ORDERS.get(orderNo);
        if (paymentOrder == null) {
            log.error("支付订单不存在，订单号：{}", orderNo);
            return false;
        }
        
        if (!"SUCCESS".equals(paymentOrder.getStatus())) {
            log.error("订单未支付成功，无法退款，订单号：{}", orderNo);
            return false;
        }
        
        // 模拟退款成功
        paymentOrder.setRefundAmount(amount);
        paymentOrder.setRefundTime(LocalDateTime.now());
        paymentOrder.setStatus("REFUNDED");
        
        // 创建退款收支明细
        try {
            com.team.order.domain.Order order = appOrderMapper.selectOrderByOrderNo(orderNo);
            if (order != null) {
                // 创建退款收支明细
                accountFlowService.createOrderRefundFlow(
                    order.getId(),
                    orderNo,
                    order.getMerchantId(),
                    amount,
                    "用户申请退款"
                );
                
                log.info("退款成功，已创建退款收支明细，订单号：{}，退款金额：{}", orderNo, amount);
            } else {
                log.warn("订单不存在，无法创建退款收支明细，订单号：{}", orderNo);
            }
        } catch (Exception e) {
            log.error("创建退款收支明细失败，订单号：{}", orderNo, e);
        }
        
        log.info("模拟退款成功，订单号：{}，退款金额：{}", orderNo, amount);
        return true;
    }
    
    /**
     * 验证回调签名
     */
    public boolean verifyCallbackSign(Map<String, String> params, String sign) {
        String generatedSign = generateMockSign(params);
        boolean isValid = generatedSign.equals(sign);
        log.info("验证回调签名：{}，结果：{}", sign, isValid);
        return isValid;
    }
    
    /**
     * 生成模拟签名
     */
    private String generateMockSign(Map<String, String> params) {
        // 简单的模拟签名算法
        StringBuilder signStr = new StringBuilder();
        params.entrySet().stream()
            .filter(entry -> !"sign".equals(entry.getKey()) && entry.getValue() != null)
            .sorted(Map.Entry.comparingByKey())
            .forEach(entry -> signStr.append(entry.getKey()).append("=").append(entry.getValue()).append("&"));
        signStr.append("key=").append(MOCK_SECRET_KEY);
        
        return java.util.UUID.randomUUID().toString().replace("-", "").substring(0, 32).toUpperCase();
    }
    
    /**
     * 生成随机字符串
     */
    private String generateNonceStr() {
        return UUID.randomUUID().toString().replace("-", "").substring(0, 32);
    }
    
    /**
     * 获取支付订单信息
     */
    public MockPaymentOrder getPaymentOrder(String orderNo) {
        return PAYMENT_ORDERS.get(orderNo);
    }
    
    /**
     * 清除所有模拟数据（用于测试）
     */
    public void clearAllData() {
        PAYMENT_ORDERS.clear();
        log.info("已清除所有模拟支付数据");
    }
    
    /**
     * 模拟支付订单内部类
     */
    public static class MockPaymentOrder {
        private String orderNo;
        private BigDecimal amount;
        private Integer payType;
        private String status;
        private LocalDateTime createTime;
        private LocalDateTime payTime;
        private String thirdPartyOrderNo;
        private String description;
        private String failReason;
        private BigDecimal refundAmount;
        private LocalDateTime refundTime;
        
        // Getters and Setters
        public String getOrderNo() { return orderNo; }
        public void setOrderNo(String orderNo) { this.orderNo = orderNo; }
        
        public BigDecimal getAmount() { return amount; }
        public void setAmount(BigDecimal amount) { this.amount = amount; }
        
        public Integer getPayType() { return payType; }
        public void setPayType(Integer payType) { this.payType = payType; }
        
        public String getStatus() { return status; }
        public void setStatus(String status) { this.status = status; }
        
        public LocalDateTime getCreateTime() { return createTime; }
        public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
        
        public LocalDateTime getPayTime() { return payTime; }
        public void setPayTime(LocalDateTime payTime) { this.payTime = payTime; }
        
        public String getThirdPartyOrderNo() { return thirdPartyOrderNo; }
        public void setThirdPartyOrderNo(String thirdPartyOrderNo) { this.thirdPartyOrderNo = thirdPartyOrderNo; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public String getFailReason() { return failReason; }
        public void setFailReason(String failReason) { this.failReason = failReason; }
        
        public BigDecimal getRefundAmount() { return refundAmount; }
        public void setRefundAmount(BigDecimal refundAmount) { this.refundAmount = refundAmount; }
        
        public LocalDateTime getRefundTime() { return refundTime; }
        public void setRefundTime(LocalDateTime refundTime) { this.refundTime = refundTime; }
    }
} 